package hotciv.variant;

import java.util.Iterator;
import java.util.List;

import hotciv.framework.*;
import hotciv.standard.*;
import hotciv.exceptions.*;

/** AlphaCiv variant implementation skeleton code. */

public class HotCivGame implements GameTesting {

	private int noTurn;
	private Player inTurn;
	private WinStrategy winstrategy;
	private MoveUnitStrategy moveunitstrategy;
	private WorldSetupStrategy worldsetupstrategy;
	protected List<Tile> world;
	
	
	
	public HotCivGame(AbstractFactory fac) {
		winstrategy = fac.createWinStrategy();
		moveunitstrategy = fac.createMoveUnitStrategy();
		worldsetupstrategy = fac.createWorldSetupStrategy();
		world = worldsetupstrategy.setupWorld(this,world);	
		//System.out.println("Game is on!");
		// INITIATES GAME!
		this.endOfTurn();
	
	}
	
	public boolean isWithinWorldLimit(Position p) {
		if( (p.getColumn() < 0) || (p.getColumn() >= Game.WORLDSIZE) ||
			(p.getRow() < 0)    || (p.getRow() >= Game.WORLDSIZE) )
			return false;
			//throw new OutsideWorldException(p+" is outside world limits!!");
		return true;
			
	}
	

	public City getCityAt(Position p) {
		this.isWithinWorldLimit(p);
		Tile t = this.getTile(p);
		if(t.getCityList().isEmpty()) return null;
		return t.getCityList().get(0);
	}
	
	public Tile getTile(Position p) {
		this.isWithinWorldLimit(p);
		return world.get( p.getRow() * Game.WORLDSIZE + p.getColumn() );
	}
	
	public Unit getUnitAt(Position p) {
		this.isWithinWorldLimit(p);
		Tile t = this.getTile(p);
		return t.getTopUnit();
	}
	
	public boolean moveUnit(Position from, Position to) {
		return moveunitstrategy.moveUnit(this, from, to);
	}
	
	public void endOfTurn() {
		if(this.getWinner() != null) {
			System.err.println(this.getPlayerInTurn()+" has WON the game!");
		}
		noTurn++;
		// A)
		restoreMoveCount(inTurn);
		
		// B)
		//produceFoodAndMaterial
		
		// C)
		//maybeProduceUnits
		
		// D)
		if(inTurn == null || inTurn == StandardPlayer.BLUE)
			inTurn = StandardPlayer.RED;
		else inTurn = StandardPlayer.BLUE;
	}

	private void restoreMoveCount(Player p) {
		Iterator<Tile> itr = world.iterator();
		while(itr.hasNext()) {
			Unit u = itr.next().getTopUnit();
			if(u != null && u.getOwner() == inTurn && u.getMoveCount() < 1)
				u.resetMoveCount();
		}
	}

	public void changeProductionInCityAt(Position p, String unitType) {
		if(this.getCityAt(p) != null)
			throw new NoCityHereException("No City here!");
		((CityTesting)this.getCityAt(p)).setProduction(unitType);
	}
	
	public void changeWorkForceFocusInCityAt(Position p, String balance) {
		if(this.getCityAt(p) != null)
			throw new NoCityHereException("No City here!");
		((CityTesting)this.getCityAt(p)).setWorkforceFocus(balance);
	}
	
	public Player getPlayerInTurn() {
		return inTurn;
	}
	
	public Player getWinner() {
		return winstrategy.getWinner(this);
	}
	
	public void addGameObserver(GameObserver observer) {
	}
	
	public int getNoRound() {
		return noTurn;
	}
	
	public int counter(Player p) {
		List<Tile> w = this.world;
		Iterator<Tile> w_itr = w.iterator();
		int i = 0;
		while(w_itr.hasNext()) { 
			Object t = w_itr.next();
			//System.out.println(i+": no "+p+" at "+ ((Tile)t).getPosition());
			if( (!((Tile)t).getUnitList().isEmpty()) && (((Tile)t).getUnitList().get(0).getOwner() == p) )  i++;
			if( (!((Tile)t).getCityList().isEmpty()) && (((Tile)t).getCityList().get(0).getOwner()) == p) i++;
		}
		return i;
	}

}
